package com.mf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mf.basic.BasicDuration;
import com.mf.basic.BasicKey;
import com.mf.entity.bo.UserBo;
import com.mf.entity.request.search.UserPageListSearch;
import com.mf.entity.request.user.*;
import com.mf.entity.vo.UserVo;
import com.mf.enums.EnableOrDisableEnum;
import com.mf.enums.GenderEnum;
import com.mf.exceptions.GraceException;
import com.mf.mapper.UserMapper;

import com.mf.result.Result;
import com.mf.service.IUserService;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.utils.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.transaction.annotation.Transactional;

/**
 * 服务实现类
 *
 * @author mf
 * @since 2024-07-18
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserBo> implements IUserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RedisOperator redisOperator;

    @Override
    public Page<UserVo> pageList(UserPageListSearch userPageListSearch) {
        Page<UserBo> page = new Page<>();
        UserBo userBo = new UserBo();
        BeanUtils.copyProperties(userPageListSearch, userBo);
        // 查询条件
        QueryWrapper<UserBo> queryWrapper = MybatisPlusUtils.getQueryWrapper(userPageListSearch,UserBo.class);

        if(VerifyUtils.isNotEmpty(userPageListSearch.getStartTime()) && VerifyUtils.isNotEmpty(userPageListSearch.getEndTime())){
            queryWrapper.between("login_time", userPageListSearch.getStartTime(), userPageListSearch.getEndTime());
        }

        Page<UserBo> userBos = userMapper.selectPage(page, queryWrapper);
        return MybatisPlusUtils.changePageDataClass(userBos, UserVo.class);
    }

    /**
     * 根据id查询用户
     */
    @Override
    public UserVo findById(Long id) {
        UserBo userBo = userMapper.selectById(id);
        if (userBo == null) {
            GraceException.display("用户不存在");
        }
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(userBo, userVo);
        return userVo;
    }

    /**
     * 修改用户状态
     */
    @Override
    public Integer changeStatusByUser(Integer status, Long id) {
        if (!EnumUtils.existsInEnum(EnableOrDisableEnum.class, status)) {
            GraceException.display("状态异常");
        }

        UserBo userBo = new UserBo();

        userBo.setId(id);
        userBo.setStatus(status);

        return userMapper.updateById(userBo);
    }

    /**
     * 用户修改密码
     */
    @Override
    public Integer userChangePwd(UserChangePwdRequest userChangePwdRequest) {
        UserBo userBo = findByNameAnd(userChangePwdRequest.getName());
        if (userBo == null) {
            GraceException.display("账号密码错误");
        }

        // 用户输入旧密码
        String userOldPwd = DigestUtils.sha256Hex(userChangePwdRequest.getOldPwd() + userBo.getSecret());
        // 用户新密码
        String newPwd = DigestUtils.sha256Hex(userChangePwdRequest.getNewPwd() + userBo.getSecret());

        if (!userOldPwd.equals(userBo.getPwd())) {
            GraceException.display("账号密码错误");
        }

        if (newPwd.equals(userBo.getPwd())) {
            GraceException.display("旧密码不能与新密码一致");
        }


        userBo.setPwd(newPwd);
        return userMapper.updateById(userBo);
    }

    /**
     * 管理员修改用户密码
     */
    @Override
    public Integer adminChangeUserPwd(AdminChangeUserPwdRequest adminChangeUserPwdRequest) {
        UserBo userBo = findByNameAnd(adminChangeUserPwdRequest.getName());
        if (userBo == null) {
            GraceException.display("没有该账号");
        }
        userBo.setPwd(DigestUtils.sha256Hex(adminChangeUserPwdRequest.getNewPwd() + userBo.getSecret()));
        return userMapper.updateById(userBo);
    }

    /**
     * 编辑
     */
    @Override
    public Void edit(UserVo userVo) {
        UserBo userBo = new UserBo();
        BeanUtils.copyProperties(userVo, userBo);

        if (VerifyUtils.isNotEmpty(userVo.getPhone()) && RegularVerificationUtils.
                validatePhoneNumber(userVo.getPhone())) {
            GraceException.display("手机号格式错误");
        }

        if (VerifyUtils.isNotEmpty(userVo.getEmail()) && RegularVerificationUtils.validateEmail(userVo.getEmail())) {
            GraceException.display("邮箱格式错误");
        }

        if (!EnumUtils.existsInEnum(GenderEnum.class, userVo.getSex())) {
            GraceException.display("性别错误");
        }

        // 禁止修改字段
        userBo.setName(null);
        userBo.setPwd(null);
        userBo.setSecret(null);
        userBo.setLoginTime(null);
        userBo.setCreateTime(null);
        userBo.setStatus(null);

        userMapper.updateById(userBo);
        return null;
    }

    /**
     * 登录
     */
    @Override
    @Transactional
    public UserTokenRequest login(UserLoginRequest userLoginRequest) {
        UserBo userBo = findByNameAnd(userLoginRequest.getName(), userLoginRequest.getSystemCode());
        if (userBo == null) {
            GraceException.display("账号密码错误");
        }

        String pwd = DigestUtils.sha256Hex(userLoginRequest.getPwd() + userBo.getSecret());
        if (pwd.equals(userBo.getPwd())) {
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(userBo, userVo);

            // 存储系统编号为登录系统编号
            userVo.setSystemCode(userLoginRequest.getSystemCode());
            String token = JWTUtil.createToken(userVo);

            // 设置token
            redisOperator.set(BasicKey.REDIS_USER_TOKEN + userVo.getNameAndId(), token,
                    BasicDuration.TOKEN_DURATION);

            // 生成刷新token
            String backRefreshToken = CommonUtils.getUUID();

            String refreshToken = backRefreshToken + ":" + token;
            redisOperator.set(BasicKey.REDIS_USER_REFRESH_TOKEN + userVo.getNameAndId(), refreshToken,
                    BasicDuration.REFRESH_TOKEN_DURATION);

            updateLoginTime(userBo.getId());
            return UserTokenRequest.builder().token(token).key(backRefreshToken).build();
        }
        GraceException.display("账号密码错误");
        return null;
    }

    /**
     * 更新最后登录时间
     */
    @Override
    public void updateLoginTime(long userId) {
        UserBo userBo = new UserBo();
        userBo.setId(userId);
        userBo.setLoginTime(DateUtil.getCurrentLocalDateTime());
        userMapper.updateById(userBo);
    }

    /**
     * 注册
     */
    @Override
    @Transactional
    public void register(UserRegisterRequest userRegisterRequest) {

        // 验证用户是否存在
        if (findByNameAnd(userRegisterRequest.getName()) != null) {
            GraceException.display("用户名称已存在");
        }


        // 保存
        UserBo userBo = new UserBo();
        BeanUtils.copyProperties(userRegisterRequest, userBo);


        userBo.setSlogan("这个人很懒，什么都没写");
        userBo.setSex(GenderEnum.UNKNOWN.value);

        // 随机生成密钥
        userBo.setSecret(CommonUtils.getRandomString(15));
        // 密码加密
        userBo.setPwd(DigestUtils.sha256Hex(userBo.getPwd() + userBo.getSecret()));

        userMapper.insert(userBo);

        Result.success();
    }

    /**
     * 根据名称系统查询用户
     */
    private UserBo findByNameAnd(String name) {
        LambdaQueryWrapper<UserBo> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(UserBo::getName, name);

        return userMapper.selectOne(userLambdaQueryWrapper);
    }

    /**
     * 根据名称系统编号查询用户
     */
    private UserBo findByNameAnd(String name, String systemCode) {
        UserBo userBo = findByNameAnd(name);

        if (userBo != null) {
            String[] code = userBo.getSystemCode().split(",");
            for (String c : code) {
                if (systemCode.equals(c)) {
                    return userBo;
                }
            }
        }
        return null;
    }

}
